//**************************************************************************************************
//
// Camera.cpp: implementation of the CCamera class.
//
// Description: basic 1st person camera - see site for more details
//
// Created by: Keith Ditchburn 15/06/01
//
//**************************************************************************************************
#include "dxstdafx.h"
#include "Camera.h"

/**************************************************************************************************
**************************************************************************************************/
CCamera::CCamera()
{
	// Set member variable defaults
	m_movementSpeed = 0.3f;
	m_rotationSpeed = 0.009f;

	// Start position
	m_position=D3DXVECTOR3(0.0f,2.0f,-4.0f);
	m_look=D3DXVECTOR3(0.0f,0.0f,1.0f);
	m_right=D3DXVECTOR3(1.0f,0.0f,0.0f);
	m_up=D3DXVECTOR3(0.0f,1.0f,0.0f);
	m_rotationChange=D3DXVECTOR3(0.0f,0.0f,0.0f);
}

/**************************************************************************************************
**************************************************************************************************/
CCamera::~CCamera()
{

}

/**************************************************************************************************
Desc: Create view matrix
Date: 24/02/00
**************************************************************************************************/
void CCamera::CalculateViewMatrix(D3DXMATRIX *view) 
{
	assert(view);

	BaseRegenerateVectors();

	// If we want to simulate YAW we must Create a Matrix that rotates around the Cameras UP vector
	D3DXMATRIX YawMatrix;
	D3DXMatrixRotationAxis(& YawMatrix, &m_up, m_rotationChange.y); 

	// Next, if we need to simulate Pitch, we now Create a Matrix that rotates around the Camera RIGHT vector
	D3DXMATRIX PitchMatrix;
	D3DXMatrixRotationAxis(& PitchMatrix, &m_right, m_rotationChange.x ); 

	// To apply the 'Yaw' we rotate the LOOK & RIGHT Vectors about the UP Vector (YawMatrix)
	D3DXVec3TransformCoord(&m_look , &m_look, &YawMatrix); 
	D3DXVec3TransformCoord(&m_right, &m_right, &YawMatrix); 
	
	// And then we rotate the LOOK & UP Vectors about the RIGHT Vector (PitchMatrix) 
	D3DXVec3TransformCoord(&m_look , &m_look, & PitchMatrix); 
	D3DXVec3TransformCoord(&m_up, &m_up, & PitchMatrix); 

	// Now set up the View Matrix
	D3DXMatrixIdentity(view);
	
	view->_11 = m_right.x; view->_12 = m_up.x; view->_13 = m_look.x;
	view->_21 = m_right.y; view->_22 = m_up.y; view->_23 = m_look.y;
	view->_31 = m_right.z; view->_32 = m_up.z; view->_33 = m_look.z;
	
	view->_41 = - D3DXVec3Dot( &m_position, &m_right ); 
	view->_42 = - D3DXVec3Dot( &m_position, &m_up );
	view->_43 = - D3DXVec3Dot( &m_position, &m_look );

	// Reset rotations
	m_rotationChange.x=0.0f;
	m_rotationChange.y=0.0f;
	m_rotationChange.z=0.0f;

}

/**************************************************************************************************
Desc: Alter position
Date: 24/02/00
**************************************************************************************************/
void CCamera::MoveUp()
{
	m_position+=(m_up*m_movementSpeed);
}

/**************************************************************************************************
Desc: Alter position
Date: 24/02/00
**************************************************************************************************/
void CCamera::MoveDown()
{
	m_position-=(m_up*m_movementSpeed);
}

/**************************************************************************************************
Desc: Alter position
Date: 15/06/01
**************************************************************************************************/
void CCamera::MoveForward()
{
	m_position+=(m_look*m_movementSpeed);
}

/**************************************************************************************************
Desc: Alter position
Date: 15/06/01
**************************************************************************************************/
void CCamera::MoveBack()
{
	m_position-=(m_look*m_movementSpeed);
}

/**************************************************************************************************
Desc: Alter position
Date: 15/06/01
**************************************************************************************************/
void CCamera::MoveLeft()
{
	m_position+=(-m_right*m_movementSpeed);
}

/**************************************************************************************************
Desc: Alter position
Date: 15/06/01
**************************************************************************************************/
void CCamera::MoveRight()
{
	m_position+=(m_right*m_movementSpeed);
}

/**************************************************************************************************
Desc: Alter rotation
Date: 15/06/01
**************************************************************************************************/
void CCamera::RotateLeft()
{
	m_rotationChange.y=-m_rotationSpeed;
}

/**************************************************************************************************
Desc: Alter rotation
Date: 15/06/01
**************************************************************************************************/
void CCamera::RotateRight()
{
	m_rotationChange.y=m_rotationSpeed;
}

/**************************************************************************************************
Desc: Mouse has moved, change into a rotation
Date: 24/02/00
**************************************************************************************************/
void CCamera::MouseMove(int dx,int dy)
{
	// note: mouse screen movement of 30 is about maximum, so scale accordingly	
	m_rotationChange.y=m_rotationSpeed*dx*0.5f;
	m_rotationChange.x=m_rotationSpeed*dy*0.5f;	
}

/**************************************************************************************************
Desc: rotation inacuracies can cause matrix to lose its 'axis' shape so regenerate
Date: 08/03/2002
**************************************************************************************************/
void CCamera::BaseRegenerateVectors()
{
	D3DXVec3Normalize(&m_look,&m_look);

	// Fix it so we are always upright, No roll.
	m_up   = D3DXVECTOR3( 0.0f, 1.0f,0.0f );

	D3DXVec3Cross(&m_right,&m_up,&m_look);

	D3DXVec3Normalize(&m_right,&m_right);

	D3DXVec3Cross(&m_up,&m_look,&m_right);

	D3DXVec3Normalize(&m_up,&m_up);
}

/**************************************************************************************************
Desc: Set position and view direction
Date: 28/07/2002
**************************************************************************************************/
void CCamera::SetView(const D3DXVECTOR3 &pos,const D3DXVECTOR3 &look)
{
	m_movementSpeed = 0.3f;
	m_rotationSpeed = 0.009f;

	m_position=pos;
	m_look=look;

	BaseRegenerateVectors();

	m_rotationChange=D3DXVECTOR3( 0.0f, 0.0f,0.0f );
}

/**************************************************************************************************
Desc: allows camera position to be altered
Date: 15/03/2003
**************************************************************************************************/
void CCamera::SetPosition(const D3DXVECTOR3 &pos)
{
	m_position=pos;

	BaseRegenerateVectors();
}
